Skip to content

Implementation of Dedicated Server in Isolation#498

Draft
kuwacom wants to merge 50 commits intosmartcmd:mainfrom
kuwacom:feature/dedicated-server
Draft

Implementation of Dedicated Server in Isolation#498
kuwacom wants to merge 50 commits intosmartcmd:mainfrom
kuwacom:feature/dedicated-server

Conversation

@kuwacom
Copy link
Contributor

@kuwacom kuwacom commented Mar 4, 2026

Description

This PR introduces a Windows64 dedicated server executable (Minecraft.Server) and expands the dedicated-server runtime/build pipeline.

Compared to the initial pull request description, the following features have been newly added:

  • interactive server console (linenoise + command completion),
  • broader server.properties support (including LAN advertise and host options),
  • world bootstrap/load behavior based on level-id,
  • Docker (Wine) runtime support and helper scripts.

Minecraft.Client changes remain focused on dedicated-server bridge compatibility.
#65

image

Changes

Dedicated Server Executable / Startup

  • Added dedicated server entrypoint and project:
    • Minecraft.Server/Windows64/ServerMain.cpp
    • Minecraft.Server/Minecraft.Server.vcxproj (+ filters)
  • Dedicated startup flow now:
    • loads server.properties defaults,
    • applies CLI overrides,
    • bootstraps world by level-id / level-name,
    • performs initial save for newly created worlds,
    • runs periodic autosave and graceful shutdown save.
  • Dedicated launch options:
    • -port, -ip/-bind, -name, -maxplayers, -seed, -loglevel, -help
    • Since the arguments can basically override server.properties, it can also be integrated into fully autonomous deployment systems like Kubernetes.

Dedicated Runtime Modules

  • Added/expanded:
    • ServerProperties (defaulting, normalization, persistence for dedicated options)
    • WorldManager (load existing world by level-id, fallback by name, or create new world)
    • ServerLogger (debug|info|warn|error)
  • Added shared server string utility layer:
    • Minecraft.Server/Common/StringUtils
    • used by logger/properties/world/console paths to avoid duplicated conversion/normalize logic.

Interactive Server Console

  • Added console runtime:
    • ServerCli, ServerCliInput, ServerCliParser, ServerCliEngine, ServerCliRegistry
    • linenoise-based input/history/completion support.
  • Added built-in commands:
    • help (?)
    • stop
    • list
    • tp (teleport)
    • gamemode (gm)
  • Added completion behavior:
    • command/alias completion,
    • player name completion,
    • gamemode token completion (survival|creative|s|c|0|1).

Minecraft.Client Bridge Changes (Dedicated Compatibility Scope)

Only dedicated-server compatibility behavior was changed in client networking paths:

  1. Minecraft.Client/MinecraftServer.h

    • Added NetworkGameInitData::dedicatedNoLocalHostPlayer.
  2. Minecraft.Client/Common/Network/GameNetworkManager.cpp

    • Added dedicated host path to skip local host ClientConnection creation.
    • Preserved host telemetry and multiplayer mode initialization behavior.
  3. Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp

    • Dedicated host startup now uses configured bind IP/port globals.
    • LAN advertising is now controlled by dedicated config (lan-advertise).
  4. Minecraft.Client/Windows64/Network/WinsockNetLayer.h/.cpp

    • Added dedicated LAN advertise global.
    • In dedicated mode, LAN discovery thread is not started.

Build / Tooling / Docs

  • Added CMake target and wiring:
    • CMakeLists.txt: MinecraftServer target + post-build asset copy
    • cmake/CopyServerAssets.cmake: minimal dedicated runtime asset copy
  • Updated solution/docs/ignore:
    • MinecraftConsoles.sln
    • COMPILE.md
    • .gitignore
  • Added Docker runtime support (Wine):
    • docker/dedicated-server/Dockerfile
    • docker/dedicated-server/entrypoint.sh
    • docker-compose.dedicated-server.yml
    • docker-build-dedicated-server.sh
    • start-dedicated-server.sh
    • README.md dedicated Docker section

kuwacom added 4 commits March 4, 2026 18:12
- Introduced `ServerMain.cpp` for the dedicated server logic, handling command-line arguments, server initialization, and network management.
- Created `postbuild_server.ps1` script for post-build tasks, including copying necessary resources and DLLs for the dedicated server.
- Added `CopyServerAssets.cmake` to manage the copying of server assets during the build process, ensuring required files are available for the dedicated server.
- Defined project filters in `Minecraft.Server.vcxproj.filters` for better organization of server-related files.
- Introduced ServerLogger for logging startup steps and world I/O operations.
- Implemented ServerProperties for loading and saving server configuration from `server.properties`.
- Added WorldManager to handle world loading and creation based on server properties.
- Updated ServerMain to integrate server properties loading and world management.
- Enhanced project files to include new source and header files for the server components.
@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 4, 2026

I hadn’t been merging upstream changes while implementing, so I’m in the middle of merging them now...

# Conflicts:
#	Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
#	Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp
#	Minecraft.Client/Windows64/Network/WinsockNetLayer.h
@gizmogoat
Copy link

gizmogoat commented Mar 4, 2026

Some things have changed in the past day-ish, watch out for incompatibilities/redundant re-implementations of these:

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 4, 2026

So -server has been added, I see.
From a quick look at the issues, it seems there are still a few world-related bugs remaining.

servers.txt is a nice addition as well.
It’s more user-friendly than -target.

kuwacom added 2 commits March 5, 2026 09:38
Since 31881af56936aeef38ff322b975fd0 , `skinHud.swf` for 720 is not included in `MediaWindows64.arc`,
the app crashes unless the virtual screen is set to HD.
@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

It was partially affected by #495, but I was able to merge it without any issues.

@haychk
Copy link

haychk commented Mar 5, 2026

is it still only LAN multiplayer only? or can worlds be opened up to more people?

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

It can be accessed from anywhere if you have a suitable network that can be accessed from the global internet (a network line that can open the specified TCP port).

In short, it's a regular server app.

@haychk
Copy link

haychk commented Mar 5, 2026

oh damn. so i could run this on a vps?

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

Yes, but since it still uses a lot of Windows API internally (to maintain compatibility), it requires a Windows system or a system that includes Windows API to run.

I would like to eventually release a Linux version and put it into Docker.

@haychk
Copy link

haychk commented Mar 5, 2026

i mean, i've tried it on linux and it works fine. i could try and create a docker image if you'd like

@gizmogoat
Copy link

I would like to eventually release a Linux version and put it into Docker.

You can run it fine on Linux without a GUI launcher via umu

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

i mean, i've tried it on linux and it works fine. i could try and create a docker image if you'd like

seriously!
That's nice.

@haychk
Copy link

haychk commented Mar 5, 2026

wine also works really well. tried lutris and has similar results to umu

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

Which one has a smaller image size?
wine or umu

@haychk
Copy link

haychk commented Mar 5, 2026

wine iirc

@void2012 void2012 marked this pull request as draft March 5, 2026 07:45
@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

Currently there are two approaches: the separated version (this pull request) and the -server option version (merged yesterday) that starts the client directly as a server. Which one should be prioritized?

The separated version modifies the world-saving logic and changes the startup logic, so integrating it into the client side would be a bit tricky.

Alternatively, it would also be possible to keep both.

@codeHusky
Copy link
Collaborator

Realistically speaking a completely separate Server executable should be our preferred way for this to work. The -server command line option is moreso jank and this is far cleaner.

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 5, 2026

If we're planning to merge the separated server in the future, I was considering removing the -server option and the unnecessary client-side logic as well. Would it be okay to leave them as they are for now?

@smartcmd
Copy link
Owner

smartcmd commented Mar 5, 2026

If we're planning to merge the separated server in the future, I was considering removing the -server option and the unnecessary client-side logic as well. Would it be okay to leave them as they are for now?

Yeah

@haychk
Copy link

haychk commented Mar 6, 2026

seems to be a bug where i cannot change the game's difficulty and enable some settings (trust players, pvp etc)
image
image
doing this all on a vps too

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 6, 2026

Sorry, that’s not written in the description, but it’s still a dummy for now.
It’s only included in the default server.properties generation ahead of time (so it can be implemented later).

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 6, 2026

doing this all on a vps too

Would it be possible to send the Dockerfile and docker-compose.yml?

@haychk
Copy link

haychk commented Mar 6, 2026

doing this all on a vps too

Would it be possible to send the Dockerfile and docker-compose.yml?

not using a docker image, which is surprising. i took your pr build and ran it on my vps. works REALLY well, minus the default server settings being awful (peaceful mode, no pvp etc)

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 8, 2026

i'm a little confused, where do worlds get stored? the server seems to autosave but... not save anything?

nevermind, you have to create the Windows64/GameHDD directory manually.

Changed it so that GameHDD is automatically created if it does not exist.

ZomkaDEV added a commit to ZomkaDEV/MinecraftConsoles that referenced this pull request Mar 8, 2026
@codeHusky
Copy link
Collaborator

If this is functional even with a few caveats I think we'd be okay to merge it in. Would rather have this be something everyone can help you with easily on main than leave you dangling in this PR for longer than needed if that's something you'd prefer. Otherwise no rush, we can wait for you to be ready.

@goshavindtburg
Copy link

When running this under Docker, how do I invoke commands to the server such as ban-ip? or is that impossible

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 10, 2026

When running this under Docker, how do I invoke commands to the server such as ban-ip? or is that impossible

By default std in is disabled so you need to enable it.
After starting with options, you need to specify the service and attach it.

tty: true
stdin_open: true

We'll commit these as defaults later.

@eff3ry
Copy link

eff3ry commented Mar 10, 2026

i got a question about the server console commands, you've created new commands and such but i can also see inside MinecraftServer.cpp alot of existing/old commands?, like time, these arent currently connected to the terminal?

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 10, 2026

i got a question about the server console commands, you've created new commands and such but i can also see inside MinecraftServer.cpp alot of existing/old commands?, like time, these arent currently connected to the terminal?

Even though the function is available, I cannot use it because I have not registered it.
More will be added in the future!

@codeHusky
Copy link
Collaborator

Is there any reason for CLI specific commands rather than a unified command implementation? Bukkit/Paper/JE uses the concept of a CommandSender which can be the console or a player, and iirc there’s some base code in the project that could be used to accomplish something like that. It’d be better for maintainability to only have one set of commands if we can help it

@eff3ry
Copy link

eff3ry commented Mar 10, 2026

please add a server properties setting that parses the world width into here
image
param->xzSize = 5*64; is chunk width
hell scale should be 8 for these large worlds

this value only effects newly generated worlds
Current limit seems to be 5*64 chunks hardcoded inside ChunkSource.h

large worlds seem like mostly ocean past the 54 chunk mark, im thinking theres another setting somewhere

@eff3ry
Copy link

eff3ry commented Mar 10, 2026

To share my findings with server World size,
To set the size of newly generated words we can define that inside the current ServerMain.cpp here:

NetworkGameInitData *param = new NetworkGameInitData();
if (config.hasSeed)
{
	param->seed = config.seed;
}

+> //Set World Size For new Worlds
+> param->xzSize = 5*64; //(5*64);
+> param->hellScale = HELL_LEVEL_SCALE_LARGE;

param->saveData = worldBootstrap.saveData;
param->settings = app.GetGameHostOption(eGameHostOption_All);
param->dedicatedNoLocalHostPlayer = true;

LogStartupStep("starting hosted network game thread");
g_NetworkManager.HostGame(0, true, false, (unsigned char)config.maxPlayers, 0);
g_NetworkManager.FakeLocalPlayerJoined();

We can also expand small worlds already generated by setting some app options, also inside ServerMain.cpp:

app.SetGameHostOption(eGameHostOption_DoMobLoot, serverProperties.doMobLoot ? 1 : 0);
app.SetGameHostOption(eGameHostOption_DoTileDrops, serverProperties.doTileDrops ? 1 : 0);
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, serverProperties.naturalRegeneration ? 1 : 0);
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, serverProperties.doDaylightCycle ? 1 : 0);


+> //Upgrade World Size
+> app.SetGameNewWorldSize(64*5, true);
+> app.SetGameNewHellScale(HELL_LEVEL_SCALE_LARGE);

StorageManager.SetSaveDisabled(serverProperties.disableSaving);
// Read world name and fixed save-id from server.properties
// Delegate load-vs-create decision to WorldManager

Currently worlds beyond 64*5 chunks wide cannot be created because of a hardcoded limit inside ChunkSource.h
i think if we just bump this #define LEVEL_MAX_WIDTH (5*64) //(6*54) we can increase the world size further
Edit: raising the LEVEL_MAX_WIDTH seems to be crashing the server upon launch,

we just need to tie these values into a Dedicated Server Config file now so that we can easily define world sizes

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 11, 2026

I’m back from my business trip, so I’ll resume working on this.

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 11, 2026

Is there any reason for CLI specific commands rather than a unified command implementation? Bukkit/Paper/JE uses the concept of a CommandSender which can be the console or a player, and iirc there’s some base code in the project that could be used to accomplish something like that. It’d be better for maintainability to only have one set of commands if we can help it

Based on a quick investigation of the current implementation, it seems that while the original codebase has structures for invoking command functionality, it was not designed to be used directly from text input.

Changing this would require significant modifications to both Minecraft.World and Minecraft.Client.

For now, the input handling, text dispatcher, and command suggestion logic are implemented on our side as a CLI-style interface.

The actual command logic required for execution (such as give, kill, time, etc.) already exists in Minecraft.World, so for the time being I think it is acceptable to invoke those through execute.

Ideally, everything should be unified in the future (preferably sooner rather than later).

@codeHusky

@codeHusky
Copy link
Collaborator

Sounds good, that can be refactored in a follow up pr then

kuwacom added 5 commits March 11, 2026 17:16
- unify duplicated implementations that were copied repeatedly
- update outdated patterns to more modern ones
`getHighestNonEmptyY()` returning `-1` occurs normally when the chunk is entirely air.
The caller (`Minecraft.World/LevelChunk.cpp:2400`) normalizes `-1` to `0`.
@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 11, 2026

The latest changes should now be integrated!
Please try it out and let me know how it works.

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 11, 2026

please add a server properties setting that parses the world width into here

Added the option.
It also seems to work correctly with existing worlds.

@uncreativeCultist
Copy link

would it be possible to add a server.properties setting for the max amount of breeding animals?

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 11, 2026

would it be possible to add a server.properties setting for the max amount of breeding animals?

They are currently defined as constants internally, so there are no plans to make them configurable.
If made configurable in the future, they will likely be placed in the config directory similar to PaperMC.

@kuwacom
Copy link
Contributor Author

kuwacom commented Mar 11, 2026

@codeHusky
I added a build step to Actions in preparation for integration.
Is that okay? If not needed, I can revert it.

image

@codeHusky
Copy link
Collaborator

codeHusky commented Mar 11, 2026

We’re definitely going to need a separate dedicated nightly server release so that’s perfect! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.